#ifndef _Faction_HPP_
#define	_Faction_HPP_
/*******************************************************************************
 ** Name: Faction.hpp                                                          **
 ** Description: Faction and faction objects                                   **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the LICENSE file within             **
 ** this distribution or at $WIKI/display/GOVT/License-software.              **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $GAME_DIR/LICENSE.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 ** Copyright (c) 2009-2011  Barry Gian James <gian@gamingods.net>            **
 ** All rights reserved.                                                      **
 ******************************************************************************/
// Portions (c) 2012 Open Design Strategies, LLC.
// Modified $Date: 2012-08-14 20:47:30 -0600 (Tue, 14 Aug 2012) $ by $Author: unknown $
#define Faction_hpp_ID   "$Id: Faction.hpp 69068 2012-08-15 02:47:30Z unknown $"

#include <odb/core.hxx>
#include <string>
//#include "common.hpp"
//#include "character.hpp"

#define DEFAULT_Faction_CP   38

// The greatest inspiration for this level of Faction detail comes from
// Spycraft v1.0 Faction manual OGL content.  Pick it up if you don't
// own it and incorporate it into your Spycraft 2.0 game.

namespace agency
{

//! The visibility level of the Faction.
enum class visibility {
    undefined, cryptic, secretive, hitmiss, general, common
};

#pragma db object table("faction_visibility")
struct FactionVisibility
{
#pragma db id
	entity_t	idvisibility_;
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
};

// TODO This should probably be in a world file somewhere
// TODO This should probably just be removed ~gian
enum class region {
    undefined, africa, asia, easteu, westeu, mideast, namerica, samerica, camerica
};

#pragma db object table("faction_region")
struct FactionRegion
{
#pragma db id
	entity_t	idregion_;
	std::string	name_;
	ushort		cost_;
};

//! area of influence
//! agents get a bonus when operating/rolling against this sphere
enum class influence {
    undefined, business, law, military, judicial, govt, cultural, crime
};

#pragma db object table("faction_influence")
struct FactionInfluence
{
#pragma db id
	entity_t	idinfluence_;
	std::string	name_;
	ushort		cost_;
};

//! influence quality
enum class quality {
    inferior, poor, average, good, excellent
};

#pragma db object table("faction_quality")
struct FactionQuality
{
#pragma db id
	entity_t	idquality_;
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
};

//! How prepared does the Faction make it's new field agents?
//! this can either give extra training points at char creation/joining
//! or offer specialized training players spend points to get
//! The number value is the Faction CP cost.
enum class preparation {
    none, ojt=0x05, orientation=0x0F, academy=0x10
};

//! how extensive is the training at this Faction
//! this training level determines the highest training course available
enum class training {
    undefined, seminar, outsourced, offsite, campus
};

#pragma db object table("faction_training")
struct FactionTraining
{
	#pragma db id
	entity_t	idfaction_training_;
	std::string	name_;
	ushort		cost_;
};

//! max level of specialist able to render aid in the field
enum class specialist {
    undefined, amateur, competent, trained, skilled, expert
};

#pragma db object table("faction_specialists")
struct FactionSpecialist
{
#pragma db id
	entity_t	idspecialist_;
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
};

//! the Faction's tolerance for its agents commiting crime
//! maybe this will effect the Faction's reputation?
enum class tolerance {
    zero,           //!< zero-tolerance for crimes
    threestrikes,   //!< three strikes and yer out
    blindeye,       //!< you haven't broken a law until you get caught
    endsmeans       //!< ends justifies the means. do what you must.
};

//! How well does the Faction value it's operatives?
enum class agentvalue {
    burn,       //!< the Faction is just out to burn you
    unknown,    //!< if you get caught, we don't know you
    strings,    //!< will pull strings to help you if you get caught
    asset       //!< agents are highly-valued assets
};

//! Some gear requires the appropriate license
enum class licensure {
    none,       //!< no license. vigilante group.
    law,        //!< law enforcement
    federal,    //!< federal Faction
    military,    //!< military
    banned
};

#pragma db object table("faction_license")
struct FactionLicensure
{
	#pragma db id
	entity_t	idfaction_license_;
	std::string	name_;
	ushort		cost_;
};

//! what assets are at the Faction's disposal?
//#pragma db value table("faction_assets")
enum class assets : uint64_t {
	AdvGarage = (1<<1),
	AdvLab = (1<<2),
	Airstrip = (1<<3),
	Armory = (1<<4),
	Classroom = (1<<5),
	CloneLab = (1<<6),
	COMSEC = (1<<7),
	Dojo = (1<<8),
	FiringRange = (1<<9),
	Harbor = (1<<10),
	Hospital = (1<<11),
	HotLab = (1<<12),
	LawOffice = (1<<13),
	MediaStudio = (1<<14),
	MilitaryDepot = (1<<15),
	MotorPool = (1<<16),
	Prison = (1<<17),
	RecordsOffice = (1<<18),
	Satellites = (1<<19),
	TrainingGround = (1<<20),
	Arena = (1<<21),
	Casino = (1<<22),
	Castle = (1<<23),
	ChopShop = (1<<24),
	CommunityCollege = (1<<25),
	DentalClinic = (1<<26),
	DesertBootCamp = (1<<27),
	DocksideWarehouse = (1<<28),
	LobbyistHQ = (1<<29),
	ExoticGreenhouse = (1<<30),
	GovtBioFacility = (1<<31),
	MilitaryBase = (1<<32),
	Museum = (1<<33),
	Newspaper = (1<<34),
	NuclearPlant = (1<<35),
	Gulag = (1<<36),
	PoliceAcademy = (1<<37),
	PropagandaStudio = (1<<38),
	PublicRelations = (1<<39),
	SoftwareFirm = (1<<40),
	SuicideBombers = (1<<41),
	SwissBankAcct = (1<<42),
	TatooParlor = (1<<43),
	UniGeneticsLab = (1<<44)

};

#pragma db object table("faction_assets")
struct FactionAssets
{
#pragma db id auto
	entity_t	idassets_;
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
	ushort		bonus_;
	entity_t	bonus_to_;
};

//#pragma db value table("faction_resources")
enum class resources : uint64_t {
	GreaseMonkey = (1<<1),
	DARPA = (1<<2),
	Topgun = (1<<3),
	EliteGuard = (1<<4),
	FiltyStinkingRich = (1<<5),
	Dungeons = (1<<6),
	FleetSupport = (1<<7),
	HigherEdu = (1<<8),
	OpenSourceSoftware = (1<<9),
	WorseThanDeath = (1<<10),
	TrainingCompound = (1<<11),
	Smuggling = (1<<12),
	GraspTheMonkeyMind = (1<<13),
	TheInCrowd = (1<<14),
	ExoticPoisons = (1<<15),
	Arsenal = (1<<16),
	Hotzones = (1<<17),
	PrivatePier = (1<<18),
	MobileMedicalUnit = (1<<19),
	LegalCounsel = (1<<20),
	PublicSupport = (1<<21),
	CrewservedGunsmith = (1<<22),
	SelfDestructMechanism = (1<<23),
	Fleet = (1<<24),
	PrivateCollection = (1<<25),
	Propaganda = (1<<26),
	IndependentEnergy = (1<<27),
	TortureChambers = (1<<28),
	CorrectionalFacility = (1<<29),
	HardenedKillers = (1<<30),
	Fanatics = (1<<31),
	PublicSympathy = (1<<32),
	WorldwidePersonDB = (1<<33),
	SatelliteNetwork = (1<<34),
	SecureComms = (1<<35),
	Martyrs = (1<<36),
	FluidAssets = (1<<37),
	SecretIDMethod = (1<<38),
	BasicCloning = (1<<39)
};

#pragma db object table("faction_resources")
struct FactionResources
{
#pragma db id auto
	entity_t	idresources_;
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
	ushort		bonus_;
	entity_t	bonus_to_;
};

//! the flavor/style of the Faction
enum class methodology {
	undefined,
    insurection,    //!< focused on foreign govt instability
    infiltration,   //!< focused on b&e
    investigation,  //!< focused on investigating <whatever>
    appropriation,  //!< um, stealing :)
    wetwork,        //!< black ops, assassination
    paramilitary,   //!< military-style operations
    coverup         //!< false info dissemination, covering tracks, hiding secret
};

#pragma db object table("faction_methodology")
struct FactionMethodology
{
#pragma db id auto
	entity_t	idmethodology_;
	std::string	name_;
	std::string	desc_;
	ushort		cost_;
	ushort		bonus_;
	entity_t	bonus_to_;
};

enum class origin {
	undefined,
    secret,         //!< origin (maybe) lost in mists of time
    founding,       //!< around time of founding of US
    ww1,            //!< (1910-1925)
    ww2,            //!< (1930-1945)
    redscare,       //!< (1950-1960)
    coldwar,        //!< (1960-1980)
    glastnost,      //!< (1980-1990) "tear down that wall"
    dotcom,         //!< (1990-2000) dot.com era
    terror          //!< (2000-present) war on terror
};

#pragma db object table("faction_origins")
struct FactionOrigins
{
	#pragma db id
	entity_t	idorigins_;
	std::string	name_;
	std::string	timeframe_;
};

enum class deptnum
{
	Unassigned,S1,S2,S3,S4,S5,S6,S7
};

enum class stated_intent
{
	advising,
	apprehension,
	control,
	collection,
	combat,
	defense,
	freedom,
	investigation,
	justice,
	observation,
	peace,
	profit,
	protection,
	research,
	security,
	science,
	stability,
	support,
	training
};

#pragma db object table("faction_intents")
struct FactionIntents
{
	entity_t	idintent_;
	std::string	name_;
	std::string	desc_;
};

enum class forte
{
	Unbreakable,		// +2 bonus fort save
	Unflappable,		// +2 bonus will save
	Uncanny,			// +2 bonus reflex save
	MasterStudents,		// +2 bonus academics check
	MasterCharmers,		// +2 bonus disposition/seduction
	MasterManipulators,	// +2 bonus blackmail/coercion
	MasterInterrogators,// +2 bonus interrogation
	MasterBrainwashers,	// +2 bonus brainwashing
	MasterTormentors,	// +2 bonus harassment
	MasterHackers,		// +2 bonus computers/electronics check
	MasterTrackers,		// +2 bonus search/surveillance
	MasterMotorists,	// +2 bonus maneuver or mechanic check
	MasterTricksters,	// +2 bonus bluff/disguise check
	MasterTravelers,	// +2 bonus language
	MasterDiplomats,	// +2 bureaucracy/diplomacy check
	MasterCryptographers,	// +2 crypto/forgery check
	MasterDetectives	// +2 gather info/surveillance check
};

#pragma db object table("faction_fortes")
struct FactionForte
{
	#pragma db id
	entity_t	idforte_;
	std::string	name_;
	ushort		bonus_;
	entity_t	bonus_to_;
};

extern std::string	dept[];

}   /* namespace Faction */


//! Each Faction has a sphere of influence
struct FactionInfluence
{

};
//struct FactionInfluence
//{
//    Faction::influence   influence;
//    Faction::quality     quality;
//    Faction::region      region;
//};

//! Support for custom naming of rank structure in your Faction
struct RankStructure
{
    std::string    rank;
    int             lvl;
};

//! @struct FactionRoster
//! @brief structure to hold the Faction's roster of personnel
#pragma db object table("faction_rosters")
struct FactionRoster
{
	entity_t		idfaction;
	#pragma db id
	entity_t		idchar;
	ushort			rank;
	agency::deptnum dept;
	bool			bOnline;
};

//! @struct ToolsRating
//! @brief The faction's tools rating
#pragma db object table("faction_tools")
struct ToolsRating
{
	#pragma db id
	entity_t	idtools_;
	ushort	K;	// tech
	ushort	S;	// support
	ushort	G;	// gadget
	ushort	T;	// tradecraft
	ushort	R;	// resource
	ushort	P;	// protective
	ushort	V;	// vehicle
	ushort	W;	// weapon
};

//! @struct HomeOffice
//! @brief A basic description of where/how/what the HO for the Faction is like.
#pragma db object table("faction_home_office")
struct HomeOffice
{
	HomeOffice() { }
	#pragma db id auto
	entity_t	idhome_office;
	std::string	desc;
};

//! @class HiddenAgenda
//! @brief The actual, true, hidden agenda of the Faction/faction.
#pragma db object table("faction_hidden_agenda")
class HiddenAgenda
{
public:
	HiddenAgenda() { }
	HiddenAgenda(const HiddenAgenda &);

	entity_t	ID() { return idfaction_agenda; }
	std::string &	Name() { return name; }
	std::string &	LevelBonus(ushort l);
	std::string &	Desc() { return desc; }

private:
	friend class odb::access;
	#pragma db id auto
	entity_t	idfaction_agenda;
	std::string	name;
//	std::string	lvl1_bonus;
//	std::string	lvl2_bonus;
//	std::string	lvl3_bonus;
//	std::string	lvl4_bonus;
//	std::string	lvl5_bonus;
	std::string	desc;
};

class Character;
//! @class Faction
//! @brief The field operative's employer
#pragma db object table("faction")
class Faction {
public:
    explicit Faction(std::string);
//    Faction(const Faction& orig);
    virtual ~Faction();
    Faction();

    static std::string StdFrenchRank(int r);
    static std::string StdMilRanks(int r);
    static std::string StdMarineRanks(int r);
    static std::string StdGovtRanks(int r);

    void	AgentLogin(std::string n);
    void	AgentLogout(std::string n);
    void	AddNewAgent(Character & c);	// add to Faction
    void	RemoveAgent(Character & c);
    void	PromoteAgent(Character &c);
    void	DemoteAgent(Character &c);

    // Getters
    const std::string &	 Name() const { return name_; }
    const agency::visibility & Visibility() const { return vis_; }
    const int	AgentMembers() const { return memberAgent_; }
    const int 		HandlerMembers() const { return memberHandler_; }
    const int 		ControlMembers() const { return memberControl_; }
    const long 		Funds() const { return funds_; }
    const agency::region Region() const { return homeregion_; }
    const std::string &	Cover() { return cover_; }
    const agency::stated_intent &	PublicIntent() const { return pubintent_; }
    const agency::training	Training()const  { return training_; }
    const agency::specialist  Specialists() const { return specialists_; }
    const agency::forte 	Forte() const { return forte_; }
    const agency::assets 	Assets() const { return assets_; }
    const entity_t		ID() const { return idfaction_; }
    const agency::origin	Origin() const { return origin_; }


    // Setters
    void			Name(std::string & n) { name_ = n; }
    void			Visibility(const agency::visibility & v) { vis_ = v; }

private:
    friend class odb::access;

	#pragma db id auto
    entity_t		idfaction_;
    std::string    	name_;			//!< name of the faction
    ToolsRating		tools_;
    std::string		owner_type_;
    entity_t		idpc_;
    entity_t		idnpc_;
    std::string		desc_;
    entity_t		idranks_;
    HiddenAgenda	agenda_;
    entity_t		idawareness_;
    HomeOffice		home_office_;
    entity_t		idlicense_;
    entity_t		idpublic_agenda_;
    entity_t		idorigins_;
    entity_t		idsphere_;
    entity_t		idtraining_;
    agency::visibility      vis_;
    int				memberAgent_;	//!< # of member agents
    int				memberHandler_;
    int				memberControl_;
    long            funds_;
    agency::region  homeregion_;
    std::string    cover_;  //!< this is the cover story/business of the Faction
    // FIXME this needs to be converted to work with ODB ORM
    //std::string    ranks[20];
    agency::stated_intent		pubintent_;
       //!< Faction's private goal(s) [maybe not known to agents]
    std::vector<FactionRoster>	roster_;
    agency::training training_;
    agency::specialist specialists_;
    agency::forte	forte_;
    agency::origin	origin_;

    agency::resources	resources_;
    agency::assets		assets_;

};


#endif	/* _Faction_HPP_ */

